package com.wy.model;

import com.baomidou.mybatisplus.annotation.TableName;
import com.wy.enums.AclResource;
import com.wy.result.ResultException;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 权限控制的关键类,这个类用来存储主体和资源之间的关系,用来确定主体能够对哪些资源进行哪些操作
 * 
 * @author 飞花梦影
 * @date 2022-01-27 15:53:28
 * @git {@link https://github.com/dreamFlyingFlower }
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("ts_acl")
public class Acl {

	private int id;

	/**
	 * 主体类型
	 */
	private String ptype;

	/**
	 * 资源的类型
	 */
	private String rtype;

	/**
	 * 主体的id
	 */
	private int pid;

	/**
	 * 资源的id
	 */
	private int rid;

	/**
	 * 对方法的操作状态,存储的是一个4个字节的整数,其实就可以存储0-31位的操作
	 * 000000....1011-->可以进行CREATE,READ,DELETE,无法进行UPDATE 数据库中存储的值是11
	 */
	private int aclState;

	public void setMenuType() {
		this.rtype = AclResource.MENU.name();
	}

	public void setControllerType() {
		this.rtype = AclResource.CONTROLLER.name();
	}

	public void setUserType() {
		this.ptype = AclResource.USER.name();
	}

	public void setRoleType() {
		this.ptype = AclResource.ROLE.name();
	}

	public void setButtonType() {
		this.rtype = AclResource.BUTTON.name();
	}

	public void setDataType() {
		this.rtype = AclResource.DATA.name();
	}

	/**
	 * 设置权限,在某个位置设置访问或者无法访问
	 * 
	 * @param index
	 * @param permit
	 */
	public void setPermission(int index, boolean permit) {
		if (index < 0 || index > 31) {
			throw new ResultException("权限的位置只能在0-31之间");
		}
		this.aclState = setBit(this.aclState, index, permit);
	}

	/**
	 * 具体进行设置
	 * 
	 * @param state
	 * @param index
	 * @param permit
	 */
	public int setBit(int state, int index, boolean permit) {
		int tmp = 1;
		tmp = tmp << index;
		if (permit) {
			state = state | tmp;
		} else {
			tmp = ~tmp;
			state = state & tmp;
		}
		return state;
	}

	/**
	 * 检查在某个位置是否可以访问
	 * 
	 * @param index
	 * @return
	 */
	public boolean checkPermission(int index) {
		int tmp = 1;
		tmp = tmp << index;
		int num = this.aclState & tmp;
		return num > 0;
	}

	public static boolean checkPermission(int index, int aclState) {
		int tmp = 1;
		tmp = tmp << index;
		int num = aclState & tmp;
		return num > 0;
	}
}